package com.tarena.lbs.coupon.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;

@Configuration
@Slf4j
public class RabbitMQConfig {

    // 延迟队列
    public static final String QR_DELAY_QUEUE = "qr.delay.queue";
    // 死信队列
    public static final String QR_DEAD_LETTER_QUEUE = "qr.dead.letter.queue";
    // 延迟交换机
    public static final String QR_DELAY_EXCHANGE = "qr.delay.exchange";
    // 死信交换机
    public static final String QR_DEAD_LETTER_EXCHANGE = "qr.dead.letter.exchange";
    // 路由键
    public static final String QR_DELAY_ROUTING_KEY = "qr.delay";
    public static final String QR_DEAD_LETTER_ROUTING_KEY = "qr.dead.letter";

    /**
     * 延迟队列 - 设置死信交换机和路由键
     */
//    @Bean
//    public Queue qrDelayQueue() {
//        Map<String, Object> args = new HashMap<>();
//        // 设置死信交换机
//        args.put("x-dead-letter-exchange", QR_DEAD_LETTER_EXCHANGE);
//        // 设置死信路由键
//        args.put("x-dead-letter-routing-key", QR_DEAD_LETTER_ROUTING_KEY);
//        // 设置队列消息过期时间（1小时），这里设置队列级别TTL，也可以设置消息级别TTL
//        args.put("x-message-ttl", 120); // 1小时
//        return new Queue(QR_DELAY_QUEUE, true, false, false, args);
//    }
//
//    /**
//     * 死信队列 - 用于处理过期的消息
//     */
//    @Bean
//    public Queue qrDeadLetterQueue() {
//        return new Queue(QR_DEAD_LETTER_QUEUE, true);
//    }
//
//    /**
//     * 延迟交换机 - Direct类型
//     */
//    @Bean
//    public DirectExchange qrDelayExchange() {
//        return new DirectExchange(QR_DELAY_EXCHANGE);
//    }
//
//    /**
//     * 死信交换机 - Direct类型
//     */
//    @Bean
//    public DirectExchange qrDeadLetterExchange() {
//        return new DirectExchange(QR_DEAD_LETTER_EXCHANGE);
//    }
//
//    /**
//     * 绑定延迟队列到延迟交换机
//     */
//    @Bean
//    public Binding delayBinding() {
//        return BindingBuilder.bind(qrDelayQueue())
//                .to(qrDelayExchange())
//                .with(QR_DELAY_ROUTING_KEY);
//    }
//
//    /**
//     * 绑定死信队列到死信交换机
//     */
//    @Bean
//    public Binding deadLetterBinding() {
//        return BindingBuilder.bind(qrDeadLetterQueue())
//                .to(qrDeadLetterExchange())
//                .with(QR_DEAD_LETTER_ROUTING_KEY);
//    }
//
//    /**
//     * JSON消息转换器
//     */
//    @Bean
//    public MessageConverter jsonMessageConverter() {
//        return new Jackson2JsonMessageConverter();
//    }
//
//    /**
//     * 配置RabbitTemplate
//     */
//    @Bean
//    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
//        RabbitTemplate template = new RabbitTemplate(connectionFactory);
//        template.setMessageConverter(jsonMessageConverter());
//        // 开启消息确认
//        template.setConfirmCallback((correlationData, ack, cause) -> {
//            if (ack) {
//                log.info("消息发送到交换机成功: {}", correlationData);
//            } else {
//                log.error("消息发送到交换机失败: {}, 原因: {}", correlationData, cause);
//            }
//        });
//        // 开启返回模式
//        template.setReturnsCallback(returned -> {
//            log.error("消息路由到队列失败: {}", returned);
//        });
//        return template;
//    }
//}
    @Bean
    public MessageConverter jsonMessageConverter() {
        return new Jackson2JsonMessageConverter();
    }

    /**
     * 配置RabbitTemplate - 放在交换机之前
     */
    @Bean
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
        RabbitTemplate template = new RabbitTemplate(connectionFactory);
        template.setMessageConverter(jsonMessageConverter());
        // 开启消息确认
        template.setConfirmCallback((correlationData, ack, cause) -> {
            if (ack) {
                log.info("消息发送到交换机成功: {}", correlationData);
            } else {
                log.error("消息发送到交换机失败: {}, 原因: {}", correlationData, cause);
            }
        });
        // 开启返回模式
        template.setReturnsCallback(returned -> {
            log.error("消息路由到队列失败: {}", returned);
        });
        return template;
    }

    /**
     * 延迟交换机 - Direct类型
     */
    @Bean
    public DirectExchange qrDelayExchange() {
        return new DirectExchange(QR_DELAY_EXCHANGE);
    }

    /**
     * 死信交换机 - Direct类型
     */
    @Bean
    public DirectExchange qrDeadLetterExchange() {
        return new DirectExchange(QR_DEAD_LETTER_EXCHANGE);
    }

    /**
     * 延迟队列 - 设置死信交换机和路由键
     */
    @Bean
    public Queue qrDelayQueue() {
        Map<String, Object> args = new HashMap<>();
        // 设置死信交换机
        args.put("x-dead-letter-exchange", QR_DEAD_LETTER_EXCHANGE);
        // 设置死信路由键
        args.put("x-dead-letter-routing-key", QR_DEAD_LETTER_ROUTING_KEY);
        // 修正时间单位：120毫秒太短了，应该是3600000毫秒（1小时）
        args.put("x-message-ttl", 120000); // 1小时 = 3600000毫秒
        return new Queue(QR_DELAY_QUEUE, true, false, false, args);
    }

    /**
     * 死信队列 - 用于处理过期的消息
     */
    @Bean
    public Queue qrDeadLetterQueue() {
        return new Queue(QR_DEAD_LETTER_QUEUE, true);
    }

    /**
     * 绑定延迟队列到延迟交换机
     */
    @Bean
    public Binding delayBinding() {
        return BindingBuilder.bind(qrDelayQueue())
                .to(qrDelayExchange())
                .with(QR_DELAY_ROUTING_KEY);
    }

    /**
     * 绑定死信队列到死信交换机
     */
    @Bean
    public Binding deadLetterBinding() {
        return BindingBuilder.bind(qrDeadLetterQueue())
                .to(qrDeadLetterExchange())
                .with(QR_DEAD_LETTER_ROUTING_KEY);
    }
}